package priv.pfz.basedao.jdbctemplate.dao.impl;

import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import priv.pfz.basedao.Utils;
import priv.pfz.basedao.info.DaoInfo;
import priv.pfz.basedao.jdbctemplate.DaoInfoParser;
import priv.pfz.basedao.jdbctemplate.SqlResult;
import priv.pfz.basedao.jdbctemplate.dao.SimpleBaseDao;
import priv.pfz.basedao.jdbctemplate.sqlprovider.*;

import javax.annotation.Nonnull;
import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;

/**
 * @author yyjxp
 * 2024/8/3 23:57
 */
public class SimpleBaseDaoImpl<Entity> implements SimpleBaseDao<Entity> {
    @Resource
    protected JdbcTemplate jdbcTemplate;

    protected final DaoInfo daoInfo = DaoInfoParser.getDaoInfo(this.getClass());
    protected final RowMapper<Entity> rowMapper = new BeanPropertyRowMapper<>((Class<Entity>) daoInfo.getEntityClass());

    @Override
    public int insert(@Nonnull Entity entity) {
        SqlResult sqlResult = InsertSqlProvider.provideSql(entity, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int batchInsert(@Nonnull Iterable<Entity> entities) {
        SqlResult sqlResult = BatchInsertSqlProvider.provideSql(entities, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
        //todo 研究jdbcTemplate功能
        //todo 如何回写自增id
    }

    @Override
    public int updateById(@Nonnull Entity entity) {
        SqlResult sqlResult = UpdateByIdSqlProvider.provideSql(entity, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int updateByUniqueKey(@Nonnull Entity entity) {
        SqlResult sqlResult = UpdateByUniqueKeySqlProvider.provideSql(entity, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int updateByExample(@Nonnull Entity entity, @Nonnull Entity example) {
        SqlResult sqlResult = UpdateByExampleSqlProvider.provideSql(entity, example, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int updateByExamples(@Nonnull Entity entity, @Nonnull Iterable<Entity> examples) {
        SqlResult sqlResult = UpdateByExamplesSqlProvider.provideSql(entity, examples, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public Entity selectById(long id) {
        SqlResult sqlResult = SelectByIdSqlProvider.provideSql(id, null, daoInfo);
        List<Entity> entities = jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
        return entities.isEmpty() ? null : entities.get(0);
    }

    @Override
    public List<Entity> listByIds(@Nonnull Iterable<Long> ids) {
        SqlResult sqlResult = ListByIdsSqlProvider.provideSql(ids, null, daoInfo);
        return jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
    }

    @Override
    public Entity selectByExample(@Nonnull Entity example) {
        SqlResult sqlResult = SelectByExampleSqlProvider.provideSql(example, null, daoInfo);
        List<Entity> entities = jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
        return entities.isEmpty() ? null : entities.get(0);
    }

    @Override
    public List<Entity> listByExample(@Nonnull Entity example) {
        SqlResult sqlResult = ListByExampleSqlProvider.provideSql(example, null, daoInfo);
        return jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
    }

    @Override
    public List<Entity> listByExamples(@Nonnull Iterable<Entity> examples) {
        SqlResult sqlResult = ListByExamplesSqlProvider.provideSql(examples, null, daoInfo);
        return jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
    }

    @Override
    public int countAll() {
        SqlResult sqlResult = CountAllSqlProvider.provideSql(null, daoInfo);
        return jdbcTemplate.queryForObject(sqlResult.getSqlTemplate(), sqlResult.getArgs(), int.class);
    }

    @Override
    public List<Entity> listAll() {
        SqlResult sqlResult = ListAllSqlProvider.provideSql(null, daoInfo);
        return jdbcTemplate.query(sqlResult.getSqlTemplate(), rowMapper, sqlResult.getArgs());
    }

    @Override
    public int deleteById(long id) {
        SqlResult sqlResult = DeleteByIdSqlProvider.provideSql(id, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int deleteByIds(@Nonnull Iterable<Long> ids) {
        SqlResult sqlResult = DeleteByIdsSqlProvider.provideSql(ids, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int deleteByExample(@Nonnull Entity example) {
        SqlResult sqlResult = DeleteByExampleSqlProvider.provideSql(example, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int deleteByExamples(@Nonnull Iterable<Entity> examples) {
        SqlResult sqlResult = DeleteByExamplesSqlProvider.provideSql(examples, null, daoInfo);
        return jdbcTemplate.update(sqlResult.getSqlTemplate(), sqlResult.getArgs());
    }

    @Override
    public int loopInsert(@Nonnull Iterable<Entity> entities) {
        Utils.checkNotNull(entities, "entities不能为null");
        Iterator<Entity> it = entities.iterator();
        int count = 0;
        while (it.hasNext()) {
            insert(it.next());
            count++;
        }
        return count;
    }

    @Override
    public int saveById(@Nonnull Entity entity) {
        try {
            return insert(entity);
        } catch (DuplicateKeyException e) {
            return updateById(entity);
        }
    }

    @Override
    public int saveByUniqueKey(@Nonnull Entity entity) {
        try {
            return insert(entity);
        } catch (DuplicateKeyException e) {
            return updateByUniqueKey(entity);
        }
    }

    @Override
    public int batchSaveById(@Nonnull Iterable<Entity> entities) {
        Utils.checkNotNull(entities, "entities不能为null");
        Iterator<Entity> it = entities.iterator();
        int count = 0;
        while (it.hasNext()) {
            saveById(it.next());
            count++;
        }
        return count;
    }

    @Override
    public int batchSaveByUniqueKey(@Nonnull Iterable<Entity> entities) {
        Utils.checkNotNull(entities, "entities不能为null");
        Iterator<Entity> it = entities.iterator();
        int count = 0;
        while (it.hasNext()) {
            saveByUniqueKey(it.next());
            count++;
        }
        return count;
    }
}
